package org.quipu;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.Collection;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.Query;
import org.quipu.domain.Book;
import org.quipu.domain.Category;
import org.quipu.utils.DaoHelper;

public class TransactionsFilter {

    public static enum Order {
        ASC,
        DESC
    }

    private Condition condition = null;
    private Order order;

    public static interface Condition {

        public String getQueryCondition();

        public Condition getNegation();

        public void setParameter(Query query);
    }

    public static abstract class ParamLessCondition implements Condition {

        @Override
        public void setParameter(Query query) {
        }
    }

//    public static abstract class TypeCondition extends ParamLessCondition {
//
//        protected String getOwnSubQuery() {
//            String a = "a" + new BigInteger(130, new SecureRandom()).toString(10).substring(0, 8);
//            return "(SELECT " + a + ".id FROM Account " + a + " WHERE " + a + ".thirdParty = FALSE)";
//        }
//
//        protected String getThirdPartySubQuery() {
//            String a = "a" + new BigInteger(130, new SecureRandom()).toString(10).substring(0, 8);
//            return "(SELECT " + a + ".id FROM Account " + a + " WHERE " + a + ".thirdParty = TRUE)";
//        }
//    }

    public static abstract class LoanCondition implements Condition {
        protected Book book = null;
        protected Collection<Long> ownIds = new LinkedList<Long>();
        protected Collection<Long> thirdpartyIds = new LinkedList<Long>();
        protected String paramOwn = "own_" + new BigInteger(130, new SecureRandom()).toString(32);
        protected String param3dparty = "thirdparty_" + new BigInteger(130, new SecureRandom()).toString(32);

        public LoanCondition(Book book) {
            this.book = book;
            ownIds = DaoHelper.getIds(book.getOwnAccounts());
            ownIds.add(Long.valueOf(-1));
            thirdpartyIds = DaoHelper.getIds(book.getThirdPartyAccounts());
            thirdpartyIds.add(Long.valueOf(-1));
        }

        protected void setOwnParemeter(Query query) {
            query.setParameter(paramOwn, ownIds);
        }

        protected void setThirdPartyParemeter(Query query) {
            query.setParameter(param3dparty, thirdpartyIds);
        }
    }

    public static abstract class Group implements Condition {
        protected Collection<Condition> conditions = new LinkedList<Condition>();
        protected String groupOperator = null;

        public void addCondition(Condition condition) {
            if(condition != null)
                conditions.add(condition);
        }

        public boolean removeCondition(Condition condition) {
            return conditions.remove(condition);
        }

        public void clear() {
            conditions.clear();
        }

        public boolean isEmpty() {
            return conditions == null || conditions.isEmpty();
        }

        @Override
        public String getQueryCondition() {
            String subquery = " (";
            for(Condition cond: conditions)
                subquery += cond.getQueryCondition() + groupOperator;
            if(subquery.length() > 2)
                subquery = subquery.substring(0, subquery.length() - groupOperator.length()) + ")";
            else
                subquery = " 1=1";
            return subquery;
        }

        @Override
        public void setParameter(Query query) {
            for(Condition cond: conditions)
                cond.setParameter(query);
        }
    }

    public static class And extends Group {
        public And() {
            groupOperator = " AND";
        }

        public Condition getNegation() {
            Or or = new Or();
            for(Condition cond: conditions)
                or.addCondition(cond.getNegation());
            return or;
        }
    }

    public static class Or extends Group {
        public Or() {
            groupOperator = " OR";
        }

        public Condition getNegation() {
            And and = new And();
            for(Condition cond: conditions)
                and.addCondition(cond.getNegation());
            return and;
        }
    }

    public static class Not implements Condition {
        private Condition condition;

        public Not() {
        }

        public Not(Condition condition) {
            this.condition = condition;
        }

        public void setCondition(Condition condition) {
            this.condition = condition;
        }

        public String getQueryCondition() {
            return condition.getNegation().getQueryCondition();
        }

        @Override
        public Condition getNegation() {
            return condition;
        }

        @Override
        public void setParameter(Query query) {
            condition.setParameter(query);
        }
    }

    public static class IsInitialBallance extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL AND t.srcAccount IS NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsNotInitialBallance();
        }
    }

    public static class IsNotInitialBallance extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL OR t.srcAccount IS NOT NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsInitialBallance();
        }
    }

    public static class IsIncome extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL AND t.dstAccount IS NOT NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsNotIncome();
        }
    }

    public static class IsNotIncome extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL OR t.dstAccount IS NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsIncome();
        }
    }

    public static class IsOutcome extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL AND t.srcAccount IS NOT NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsNotOutcome();
        }
    }

    public static class IsNotOutcome extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL OR t.srcAccount IS NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsOutcome();
        }
    }

    public static class IsLocalTransfer extends LoanCondition {

        public IsLocalTransfer(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL AND t.srcAccount.id IN (:" + paramOwn + ") AND t.dstAccount.id IN (:" + paramOwn + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsNotLocalTransfer(book);
        }

        @Override
        public void setParameter(Query query) {
            setOwnParemeter(query);
        }
    }

    public static class IsNotLocalTransfer extends LoanCondition {

        public IsNotLocalTransfer(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL OR t.srcAccount IS NULL OR t.srcAccount.id IN (:" + param3dparty + ") OR t.dstAccount IS NULL OR t.dstAccount.id IN (:" + param3dparty + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsLocalTransfer(book);
        }

        @Override
        public void setParameter(Query query) {
            setThirdPartyParemeter(query);
        }
    }

    public static class IsIncomeLoan extends LoanCondition {

        public IsIncomeLoan(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL AND t.srcAccount.id IN (:" + param3dparty + ") AND t.dstAccount.id IN (:" + paramOwn + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsNotIncomeLoan(book);
        }

        @Override
        public void setParameter(Query query) {
            setOwnParemeter(query);
            setThirdPartyParemeter(query);
        }
    }

    public static class IsNotIncomeLoan extends LoanCondition {

        public IsNotIncomeLoan(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL OR t.srcAccount IS NULL OR t.srcAccount.id IN (:" + paramOwn + ") OR t.dstAccount IS NULL OR t.dstAccount.id IN (:" + param3dparty + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsIncomeLoan(book);
        }

        @Override
        public void setParameter(Query query) {
            setOwnParemeter(query);
            setThirdPartyParemeter(query);
        }
    }

    public static class IsOutcomeLoan extends LoanCondition {

        public IsOutcomeLoan(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NULL AND t.srcAccount.id IN (:" + paramOwn + ") AND t.dstAccount.id IN (:" + param3dparty + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsNotOutcomeLoan(book);
        }

        @Override
        public void setParameter(Query query) {
            setOwnParemeter(query);
            setThirdPartyParemeter(query);
        }
    }

    public static class IsNotOutcomeLoan extends LoanCondition {

        public IsNotOutcomeLoan(Book book) {
            super(book);
        }

        @Override
        public String getQueryCondition() {
            return " (t.category IS NOT NULL OR t.srcAccount IS NULL OR t.srcAccount.id IN (:" + param3dparty + ") OR t.dstAccount IS NULL OR t.dstAccount.id IN (:" + paramOwn + "))";
        }

        @Override
        public Condition getNegation() {
            return new IsOutcomeLoan(book);
        }

        @Override
        public void setParameter(Query query) {
            setOwnParemeter(query);
            setThirdPartyParemeter(query);
        }
    }

    public static class DateEquals implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateEquals(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date = :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateNotEquals(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class DateNotEquals implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateNotEquals(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date != :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateEquals(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class DateEqualsBefore implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateEqualsBefore(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date <= :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateAfter(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class DateBefore implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateBefore(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date < :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateEqualsAfter(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class DateEqualsAfter implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateEqualsAfter(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date >= :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateBefore(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class DateAfter implements Condition {
        private java.sql.Date date;
        private String param = "date_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DateAfter(Date date) {
            this.date = new java.sql.Date(date.getTime());
        }

        @Override
        public String getQueryCondition() {
            return " t.date > :" + param;
        }

        @Override
        public Condition getNegation() {
            return new DateEqualsBefore(date);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, date);
        }
    }

    public static class SrcIs implements Condition {
        private Long srcAccountId;
        private String param = "src_" + new BigInteger(130, new SecureRandom()).toString(32);

        public SrcIs(Long accountId) {
            srcAccountId = accountId;
        }

        public String getQueryCondition() {
            if(srcAccountId == null)
                return " t.srcAccount IS NULL";
            else
                return " t.srcAccount IS NOT NULL AND t.srcAccount.id = :" + param;
        }

        public Condition getNegation() {
            return new SrcIsNot(srcAccountId);
        }

        public void setParameter(Query query) {
            if(srcAccountId != null)
                query.setParameter(param, srcAccountId);
        }
    }

    public static class SrcIsNot implements Condition {
        private Long srcAccountId;
        private String param = "src_" + new BigInteger(130, new SecureRandom()).toString(32);

        public SrcIsNot(Long accountId) {
            srcAccountId = accountId;
        }

        public String getQueryCondition() {
            if(srcAccountId == null)
                return " t.srcAccount IS NOT NULL";
            else
                return " t.srcAccount IS NULL OR t.srcAccount.id != :" + param;
        }

        public Condition getNegation() {
            return new SrcIs(srcAccountId);
        }

        public void setParameter(Query query) {
            if(srcAccountId != null)
                query.setParameter(param, srcAccountId);
        }
    }

    public static abstract class AccountsCondition implements Condition {
        protected Collection<Long> accountIds = new LinkedList<Long>();
        protected String param = "accounts_" + new BigInteger(130, new SecureRandom()).toString(32);

        public AccountsCondition(Collection<Long> accountIds) {
            this.accountIds.addAll(accountIds);
            this.accountIds.add(Long.valueOf(-1));
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, accountIds);
        }
    }

    public static class DstIs implements Condition {
        private Long dstAccountId;
        private String param = "dst_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DstIs(Long accountId) {
            dstAccountId = accountId;
        }

        public String getQueryCondition() {
            if(dstAccountId == null)
                return " t.dstAccount IS NULL";
            else
                return " t.dstAccount IS NOT NULL AND t.dstAccount.id = :" + param;
        }

        public Condition getNegation() {
            return new DstIsNot(dstAccountId);
        }

        public void setParameter(Query query) {
            if(dstAccountId != null)
                query.setParameter(param, dstAccountId);
        }
    }

    public static class DstIsNot implements Condition {
        private Long dstAccountId;
        private String param = "dst_" + new BigInteger(130, new SecureRandom()).toString(32);

        public DstIsNot(Long accountId) {
            dstAccountId = accountId;
        }

        public String getQueryCondition() {
            if(dstAccountId == null)
                return " t.dstAccount IS NOT NULL";
            else
                return " t.dstAccount IS NULL OR t.dstAccount.id != :" + param;
        }

        public Condition getNegation() {
            return new DstIs(dstAccountId);
        }

        public void setParameter(Query query) {
            if(dstAccountId != null)
                query.setParameter(param, dstAccountId);
        }
    }

    public static class SrcAre extends AccountsCondition {

        public SrcAre(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.srcAccount.id IN (:" + param + "))";
            else
                return " 1=2";
        }

        @Override
        public Condition getNegation() {
            return new SrcAreNot(accountIds);
        }
    }

    public static class SrcAreNot extends AccountsCondition {

        public SrcAreNot(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.srcAccount.id NOT IN (:" + param + "))";
            else
                return " 1=1";
        }

        @Override
        public Condition getNegation() {
            return new SrcAre(accountIds);
        }
    }

    public static class DstAre extends AccountsCondition {

        public DstAre(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.dstAccount.id IN (:" + param + "))";
            else
                return " 1=2";
        }

        @Override
        public Condition getNegation() {
            return new DstAreNot(accountIds);
        }
    }

    public static class DstAreNot extends AccountsCondition {

        public DstAreNot(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.dstAccount.id NOT IN (:" + param + "))";
            else
                return " 1=1";
        }

        @Override
        public Condition getNegation() {
            return new DstAre(accountIds);
        }
    }

    public static class AccountsAre extends AccountsCondition {

        public AccountsAre(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.srcAccount.id IN (:" + param + ") OR t.dstAccount.id IN (:" + param + "))";
            else
                return " 1=2";
        }

        @Override
        public Condition getNegation() {
            return new AccountsAreNot(accountIds);
        }
    }

    public static class AccountsAreNot extends AccountsCondition {

        public AccountsAreNot(Collection<Long> accountIds) {
            super(accountIds);
        }

        @Override
        public String getQueryCondition() {
            if(accountIds != null && !accountIds.isEmpty())
                return " (t.srcAccount.id NOT IN (:" + param + ") AND t.dstAccount.id NOT IN (:" + param + "))";
            else
                return " 1=1";
        }

        @Override
        public Condition getNegation() {
            return new AccountsAre(accountIds);
        }
    }

    public static abstract class TagsCondition implements Condition {
        protected Collection<Long> tagIds = new LinkedList<Long>();
        protected String param = "tags_" + new BigInteger(130, new SecureRandom()).toString(32);

        public TagsCondition(Collection<Long> tagIds) {
            this.tagIds.addAll(tagIds);
            this.tagIds.add(Long.valueOf(-1));
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, tagIds);
        }
    }

    public static class TagsAre extends TagsCondition {

        public TagsAre(Collection<Long> tagIds) {
            super(tagIds);
        }

        @Override
        public String getQueryCondition() {
            if(tagIds != null && !tagIds.isEmpty())
//                return " (t.tagMapping.tag.id IN (:" + param + "))";
                return " (t.id IN (SELECT tm.transaction.id FROM TransactionTagMap tm WHERE tm.tag.id IN (:" + param + ")))";
            else
                return " 1=2";
        }

        @Override
        public Condition getNegation() {
            return new TagsAreNot(tagIds);
        }
    }

    public static class TagsAreNot extends TagsCondition {

        public TagsAreNot(Collection<Long> tagIds) {
            super(tagIds);
        }

        @Override
        public String getQueryCondition() {
            if(tagIds != null && !tagIds.isEmpty())
                return " (t.tagMapping.tag.id NOT IN (:" + param + "))";
            else
                return " 1=1";
        }

        @Override
        public Condition getNegation() {
            return new TagsAre(tagIds);
        }
    }

    public static abstract class CategoryCondition implements Condition {
        protected void fillAllChildsId(Category category, List<Long> ids) {
            if(ids == null)
                return;
            if(category == null)
                ids.add(null);
            else {
                ids.add(category.getId());
                for(Category child: category.getChilds())
                    fillAllChildsId(child, ids);
            }
        }
    }

    public static class IsInCategory extends CategoryCondition {
        private Category category;
        private String param = "category_" + new BigInteger(130, new SecureRandom()).toString(32);

        public IsInCategory(Category category) {
            this.category = category;
        }

        @Override
        public String getQueryCondition() {
            if(category != null)
                return " (t.category IS NOT NULL AND t.category.id IN (:" + param + "))";
            else
                return " (t.category IS NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsNotInCategory(category);
        }

        @Override
        public void setParameter(Query query) {
            if(category != null) {
                List<Long> ids = new LinkedList<Long>();
                fillAllChildsId(category, ids);
                query.setParameter(param, ids);
            }
        }
    }

    public static class IsNotInCategory extends CategoryCondition {
        private Category category;
        private String param = "category_" + new BigInteger(130, new SecureRandom()).toString(32);

        public IsNotInCategory(Category category) {
            this.category = category;
        }


        @Override
        public String getQueryCondition() {
            if(category != null)
                return " (t.category IS NULL OR t.category.id NOT IN (:" + param + "))";
            else
                return " (t.category IS NOT NULL)";
        }

        @Override
        public Condition getNegation() {
            return new IsInCategory(category);
        }

        @Override
        public void setParameter(Query query) {
            if(category != null) {
                List<Long> ids = new LinkedList<Long>();
                fillAllChildsId(category, ids);
                query.setParameter(param, ids);
            }
        }
    }

    public static class CurrencyIs implements Condition {
        private Long currencyId;
        private String param = "currency_" + new BigInteger(130, new SecureRandom()).toString(32);

        public CurrencyIs(Long currencyId) {
            this.currencyId = currencyId;
        }


        @Override
        public String getQueryCondition() {
            return " t.currency.id = :" + param;
        }
        
        @Override
        public Condition getNegation() {
            return new CurrencyIsNot(currencyId);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, currencyId);
        }
    }

    public static class CurrencyIsNot implements Condition {
        private Long currencyId;
        private final String param = "currency_" + new BigInteger(130, new SecureRandom()).toString(32);

        public CurrencyIsNot(Long currencyId) {
            this.currencyId = currencyId;
        }


        @Override
        public String getQueryCondition() {
            return " t.currency.id != :" + param;
        }
        
        @Override
        public Condition getNegation() {
            return new CurrencyIs(currencyId);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, currencyId);
        }
    }

    public static class PaymentCurrencyIs implements Condition {
        private Long paymentCurrencyId;
        private String param = "paymentCurrency_" + new BigInteger(130, new SecureRandom()).toString(32);

        public PaymentCurrencyIs(Long paymentCurrencyId) {
            this.paymentCurrencyId = paymentCurrencyId;
        }


        @Override
        public String getQueryCondition() {
            return " (t.paymentCurrency IS NOT NULL AND t.paymentCurrency.id = :" + param + ")";
        }
        
        @Override
        public Condition getNegation() {
            return new PaymentCurrencyIsNot(paymentCurrencyId);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, paymentCurrencyId);
        }
    }

    public static class PaymentCurrencyIsNot implements Condition {
        private Long paymentCurrencyId;
        private final String param = "paymentCurrency_" + new BigInteger(130, new SecureRandom()).toString(32);

        public PaymentCurrencyIsNot(Long paymentCurrencyId) {
            this.paymentCurrencyId = paymentCurrencyId;
        }


        @Override
        public String getQueryCondition() {
            return " (t.paymentCurrency IS NULL OR t.paymentCurrency.id != :" + param + ")";
        }
        
        @Override
        public Condition getNegation() {
            return new PaymentCurrencyIs(paymentCurrencyId);
        }

        @Override
        public void setParameter(Query query) {
            query.setParameter(param, paymentCurrencyId);
        }
    }

    public static class IsCurrencyConvertion extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " t.paymentCurrency IS NOT NULL";
        }

        @Override
        public Condition getNegation() {
            return new IsNotCurrencyConvertion();
        }
    }

    public static class IsNotCurrencyConvertion extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " t.paymentCurrency IS NULL";
        }

        @Override
        public Condition getNegation() {
            return new IsCurrencyConvertion();
        }
    }

    public static class IsApproved extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " t.approved = TRUE";
        }

        @Override
        public Condition getNegation() {
            return new IsNotApproved();
        }
    }

    public static class IsNotApproved extends ParamLessCondition {
        @Override
        public String getQueryCondition() {
            return " t.approved = FALSE";
        }

        @Override
        public Condition getNegation() {
            return new IsApproved();
        }
    }

/*
    public static class BookIs implements Condition {
        private ForAccounts forAccounts = null;
        private String param = "book_" + new BigInteger(130, new SecureRandom()).toString(32);

        public BookIs(Book book) {
            if(book != null)
                forAccounts = new ForAccounts(book.getOwnAccounts());
        }

        public String getQueryCondition() {
            if(forAccounts != null)
                return forAccounts.getQueryCondition();
            else
                return " 1=2";
        }

        public Condition getNegation() {
            throw new UnsupportedOperationException("BookIsNot condition is useless");
        }

        public void setParameter(Query query) {
            if(forAccounts != null)
                forAccounts.setParameter(query);
        }
    }
*/
    public TransactionsFilter() {
    }

    public TransactionsFilter(Condition condition) {
        this.condition = condition;
    }

    public void setCondition(Condition condition) {
        this.condition = condition;
    }

    public void normalize() {
    }

    public String getQueryConditions() {
        return (condition != null? condition.getQueryCondition(): " 1=1");
    }

    public void setParameter(Query query) {
        if(condition != null) {
            condition.setParameter(query);
        }
    }

    public Order getOrder() {
        return order;
    }

    public void setOrder(Order order) {
        this.order = order;
    }
}
